package com.wj.crm.service;

import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.wj.crm.base.BaseService;
import com.wj.crm.dao.ModuleMapper;
import com.wj.crm.dao.PermissionMapper;
import com.wj.crm.model.TreeModel;
import com.wj.crm.utils.AssertUtil;
import com.wj.crm.vo.Module;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author WangJin
 * @version 1.0
 * @date 2022/1/15 18:41
 */
@Service
public class ModuleService extends BaseService<Module,Integer> {
    @Autowired
    private ModuleMapper moduleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    public List<TreeModel> queryAllModules(Integer roleId){

        //查询所有的资源列表
        List<TreeModel> treeModelList = moduleMapper.queryAllModules();
        //查询指定角色已经授权过的资源列表（查询角色拥有资源ID）
        List<Integer> permissionIds = permissionMapper.queryRoleHasModuleIdsByRoleId(roleId);
        //判断角色是否拥有角色id
        if(permissionIds != null && permissionIds.size() > 0){
            //循环所有的资源列表，判断用户拥有的资源id中是否有匹配的，如果有，则设置checked属性true
            treeModelList.forEach(treeModel -> {
                //判断角色拥有的资源id是否有当前遍历的资源id
                if(permissionIds.contains(treeModel.getId())){
                    treeModel.setChecked(true);
                }
            });
        }
       return treeModelList;
    }

    //查询资源数据
    public Map<String,Object> queryAllModuleList(){
        Map<String,Object> map = new HashMap<>();
        //查询资源列表
        List<Module> moduleList = moduleMapper.queryModuleList();
        map.put("code",0);
        map.put("msg","");
        map.put("count",moduleList.size());
        map.put("data",moduleList);

        return map;
    }

    /**
     * 1.参数校验
     * id 非空 记录存在
     * 模块名-module_name
     * 非空 同一层级下模块名唯一
     * url
     * 二级菜单 非空 不可重复
     * 上级菜单-parent_id
     * 二级|三级菜单 parent_id 非空 必须存在
     * 层级-grade
     * 非空 0|1|2
     * 权限码 optValue
     * 非空 不可重复
     后端核心代码
     控制层核心代码
     * 2.参数默认值设置
     * update_date
     * 3.执行更新 判断结果
     */
    @Transactional(propagation = Propagation.REQUIRED)
    public void addModule(Module module){
        //1.参数校验
        //层级 grade 非空 0|1|2
        Integer grade = module.getGrade();
        AssertUtil.isTrue( null == grade || !(grade == 0 || grade == 1 || grade == 2),"菜单层级不合适！");

        //模块名称 moduleName 非空
        AssertUtil.isTrue(StringUtils.isBlank(module.getModuleName()),"模块名称不能为空！");
        //模块名称 moduleName 同一层级下模块名称唯一
        AssertUtil.isTrue(null != moduleMapper.queryModuleByGradeAndModuleName(grade,module.getModuleName()),"该层级下模块名称已存在！");

        if(grade == 1) {
            //地址 url 二级菜单（grade=1） 非空
            AssertUtil.isTrue(StringUtils.isBlank(module.getUrl()), "URL不能为空！");
            //地址 url 二级菜单（grade=1） 且同一层级下不可重复
            AssertUtil.isTrue(null != moduleMapper.queryModuleBygradeAndUrl(grade, module.getUrl()), "URL已存在！");
        }

        //父级菜单 parentId 一级菜单（目录 grade =0）  parentId设置-1 为目录
        if(grade == 0){
            module.setParentId(-1);
        }
        //父级菜单 parentId 二级|三级菜单 （菜单|按钮 grade = 1|2） 非空，父级菜单必须存在
        if(grade != 0){
            //非空
            AssertUtil.isTrue(null == module.getParentId(),"父级菜单不能为空！");
            //父级菜单必须存在（将父级菜单的Id作为主键，查询资源记录）
            AssertUtil.isTrue(null == moduleMapper.selectByPrimaryKey(module.getParentId()),"父级菜单必须存在！");
        }

        //权限码 optValue  非空
        AssertUtil.isTrue(StringUtils.isBlank(module.getOptValue()),"权限码不能为空！");
        //权限码 optValue 不可重复
        AssertUtil.isTrue(null != moduleMapper.queryModuleByOptValue(module.getOptValue()),"权限码已存在！");

        //设置默认值
        //是否有效 isValid
        module.setIsValid((byte) 1);
        //创建createDate 系统时间
        module.setCreateDate(new Date());
        //修改时间update 系统时间
        module.setUpdateDate(new Date());

        //执行添加操作，判断影响行数
        AssertUtil.isTrue(moduleMapper.insertSelective(module) < 1 , "资源添加失败！");
    }

        @Transactional(propagation = Propagation.REQUIRED)
        public void updateModule(Module module){
            //1.参数校验
            //id 非空，数据存在
            //非空判断
            AssertUtil.isTrue(null == module.getId(),"待更新记录不存在！");
            //通过id查询资源对象
            Module temp = moduleMapper.selectByPrimaryKey(module.getId());
            //判断记录是否存在
            AssertUtil.isTrue(null == temp,"待更新记录不存在！");

            //层级 grade 非空 0|1|2
            Integer grade = module.getGrade();
            AssertUtil.isTrue( null == grade || !(grade == 0 || grade == 1 || grade == 2),"菜单层级不合适！");
            //模块名称 moduleName 非空
            AssertUtil.isTrue(StringUtils.isBlank(module.getModuleName()),"模块名称不能为空！");
            //通过层级与模块名称查询资源对象
            temp = moduleMapper.queryModuleByGradeAndModuleName(grade, module.getModuleName());
            if(temp != null){
                AssertUtil.isTrue(!(temp.getId().equals(module.getId())),"该层级下菜单名已存在！");
            }

            //地址 url 二级菜单（grade=1） ，非空且同一层级下不可重复（不包括当前修改记录本身）
            if(grade == 1){
                AssertUtil.isTrue(StringUtils.isBlank(module.getUrl()),"菜单URL不能为空！");
                //通过层级与菜单URL查询资源对象
                temp = moduleMapper.queryModuleBygradeAndUrl(grade,module.getUrl());
                //判断是否存在
                if(temp != null){
                    AssertUtil.isTrue(!(temp.getId()).equals(module.getId()),"该层级下菜单名已存在！");
                }
            }

            //授权码 optValue 非空，不可重复（包含当前修改记录本身）
            AssertUtil.isTrue(StringUtils.isBlank(module.getOptValue()),"权限码不能为空！");
            //通过权限码查询资源对象
            temp = moduleMapper.queryModuleByOptValue(module.getOptValue());
            //判断是否为空
            if(temp != null){
                AssertUtil.isTrue(!(temp.getId()).equals(module.getId()),"权限码已存在！");
            }

            //设置参数默认值
            //修改时间，系统当前时间
            module.setUpdateDate(new Date());

            //执行更新操作，判断影响行数
            AssertUtil.isTrue(moduleMapper.updateByPrimaryKeySelective(module) < 1,"修改资源失败！");
        }

        //删除资源
    @Transactional(propagation = Propagation.REQUIRED)
    public void deleteModule(Integer id) {
        //判断id是否为空
        AssertUtil.isTrue(null == id,"待删除记录不存在！");
        //通过id查询资源对象
        Module temp = moduleMapper.selectByPrimaryKey(id);
        //判断资源对象是否为空
        AssertUtil.isTrue(null == temp,"待删除记录不存在！");

        //如果当前资源存在记录（将id当做父id查询资源记录）
        Integer count = moduleMapper.queryModuleByParentId(id);
        //如果存在记录，则不可删除
        AssertUtil.isTrue(count > 0,"该资源存在子记录，不可删除！");

        //通过资源id查询权限表中是否存在数据
        count = permissionMapper.countPermissionByModuleId(id);
        //判断是否存在，存在则删除
        if(count > 0){
            //删除指定资源id的权限记录
            permissionMapper.deletePermissionByModuleId(id);
        }

        //设置记录无效
        temp.setIsValid((byte) 0);
        temp.setUpdateDate(new Date());

        //执行更新操作
        AssertUtil.isTrue(moduleMapper.updateByPrimaryKeySelective(temp) < 1,"删除资源失败！");
    }
}
